﻿using UnityEngine;

namespace Panda.UI.Runtime
{
    public class BasePage : MonoBehaviour, IPage
    {
        
        [SerializeField]
        private PageState pageState;
        public PageState PageState { get => pageState; set => pageState = value; }
        public object Data { get; set; }
        public bool IsPopup => isPopup;

        bool IPage.IsInInAnim
        {
            get => isInInAnim;
            set => isInInAnim = value;
        }

        bool IPage.IsInOutAnim
        {
            get => isInOutAnim;
            set => isInOutAnim = value;
        }

        public IRouter Router { get; set; }
        public IPage SourcePage { get; set; }

        public ATransition InTransition
        {
            get => inTransition;
            set => inTransition = value;
        }

        public ATransition OutTransition
        {
            get => outTransition;
            set => outTransition = value;
        }

        [SerializeField]
        private bool isPopup;
        [SerializeField]
        private ATransition inTransition;
        [SerializeField]
        private ATransition outTransition;
        
        [Space]
        [SerializeField]
        private bool isInInAnim;
        [SerializeField]
        private bool isInOutAnim;

        protected CanvasGroup canvasGroup;

        public void Load()
        {
            canvasGroup = gameObject.GetComponent<CanvasGroup>();
            if (canvasGroup == null)
            {
                canvasGroup = gameObject.AddComponent<CanvasGroup>();
            }
            
            PageState = PageState.Hided;
            isInInAnim = false;
            isInOutAnim = false;
            
            OnLoad();
        }

        public void Show(bool fromBack)
        {
            StopTransitionIfCurrentPlaying();
            gameObject.SetActive(true);
   
            PageState = PageState.Showed | PageState.InInAnim;
            OnShow();

            if (fromBack == false)
            {
                transform.SetAsLastSibling();
            }
            
            StartInTransition();
        }

        public void Hide()
        {
            StopTransitionIfCurrentPlaying();
            
            PageState = PageState.Hided | PageState.InOutAnim;
            StartOutTransition();
        }

        public void Cover()
        {
            PageState |= PageState.Covered;
            OnCover();
        }

        public void Recover()
        {
            PageState ^= PageState.Covered;
            OnRecover();
        }

        public virtual void Back()
        {
            var curPage = (BasePage)Router.GetCurrentPage(); 
            if (curPage == this)
            {
                Router.NavigateBack(null, null, null);
            }
            else
            {
                Debug.LogWarning($"Cannot back because this is not current window, current is : {curPage}, me is : {this}");
            }
        }

        private void StopTransitionIfCurrentPlaying()
        {
            if (isInInAnim && inTransition)
            {
                inTransition.AheadComplete();
            }

            if (isInOutAnim && outTransition)
            {
                outTransition.AheadComplete();
            }
        }

        private void StartInTransition()
        {
            canvasGroup.blocksRaycasts = false;
            
            isInInAnim = true;
            if (inTransition)
            {
                inTransition.Animate(transform, InTransitionDone);
            }
            else
            {
                InTransitionDone();
            }
        }

        private void InTransitionDone()
        {
            isInInAnim = false;
            PageState ^= PageState.InInAnim;
            OnInTransitionDone();

            
            canvasGroup.blocksRaycasts = true;
        }

        private void StartOutTransition()
        {
            canvasGroup.blocksRaycasts = false;
            
            isInOutAnim = true;
            
            OnOutTransitionStart();
            if (outTransition)
            {
                outTransition.Animate(transform, OutTransitionDone);
            }
            else
            {
                OutTransitionDone();
            }
        }

        private void OutTransitionDone()
        {
            isInOutAnim = false;
            PageState ^= PageState.InOutAnim;
            OnHide();
            gameObject.SetActive(false);
            
            canvasGroup.blocksRaycasts = true;
        }

        public void Unload()
        {
            OnUnload();
        }

        public IPage Clone()
        {
            return Instantiate(this, transform.parent, false);
        }
        
        /// <summary>
        /// 监听页面加载
        /// </summary>
        protected virtual void OnLoad()
        {
        }

        /// <summary>
        /// 监听页面显示，入场动画开始前
        /// </summary>
        protected virtual void OnShow()
        {
        }

        /// <summary>
        /// 监听页面隐藏,出场动画完成后
        /// </summary>
        protected virtual void OnHide()
        {
        }

        protected virtual void OnCover()
        {
        }

        protected virtual void OnRecover()
        {
        }

        /// <summary>
        /// 监听入场动画完成
        /// </summary>
        protected virtual void OnInTransitionDone()
        {
        }
        
        /// <summary>
        /// 监听出场动画开始
        /// </summary>
        protected virtual void OnOutTransitionStart()
        {
        }

        /// <summary>
        /// 监听页面卸载
        /// </summary>
        protected virtual void OnUnload()
        {
        }
    }
}